package gui;

import static com.googlecode.charts4j.Color.*;

import jade.core.AID;
import jade.core.Agent;
import jade.tools.gui.AIDAddressList;

import jade.util.leap.HashMap;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import statics.TradingConst;

import com.googlecode.charts4j.*;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.Shape;
import com.googlecode.charts4j.collect.ImmutableList;

import agents.RetailerAgent;

public class RetailerGUI extends JFrame implements ActionListener, FocusListener 
{
	
	private static final int MAX_WIDTH = 820;
	private static final int MAX_HEIGHT = 450;
	private static final int CHART_WIDTH = 400;
	private static final int CHART_HEIGHT = 250;
	protected int NUM_POINTS = (int)Math.ceil((double)TradingConst.HOURS_IN_DAY/((double)TradingConst.RETAILER_AGENT_MIN_TO_UPDATE_PRICE/TradingConst.MIN_IN_HOUR));
	
	protected RetailerAgent myRetailerAgent;
    
	JPanel pnlGraph;
    
    private JPanel pnlSettings = new JPanel();
    private JLabel lblSalesTarget;
    private JTextField tfSalesTarget;
    private JButton btnSetSalesTarget;
    
    private JPanel mainPane = new JPanel();

	private LineChart chartPrice;
	private LineChart chartSales;
	
	private ArrayList<Double> CurrentPriceDollars;
	private ArrayList<Double> powerPercent;
	private ArrayList<Double> salesPercent;

	private JLabel lblGraphImageBuffPrice;
	private JLabel lblGraphImageBuffSales;
	private JLabel lblRetailerPriceImage;
	private JLabel lblRetailerSalesImage;
	
	public RetailerGUI(RetailerAgent a) 
	{
		super(a.getAID().getName());
		myRetailerAgent = a;
		
		InitUIComponents();
		InitChart();
		UpdateChart(0, myRetailerAgent.getCurrentPrice(), 1.0, 0.0);
    }
	
	private void InitUIComponents() 
	{
		setBounds(0,0,MAX_WIDTH, MAX_HEIGHT);
        
        //Graph
        pnlGraph = new JPanel();
        //pnlGraph.setLayout(new BorderLayout());
        pnlGraph.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
        lblRetailerSalesImage = new JLabel();
        lblRetailerSalesImage.setVisible(true);
        lblRetailerPriceImage = new JLabel();
        lblRetailerPriceImage.setVisible(true);
        
        //Settings
        pnlSettings.setLayout(new FlowLayout());
        pnlSettings.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
        lblSalesTarget = new JLabel("Set sales percentage target");
        pnlSettings.add(lblSalesTarget);
        tfSalesTarget = new JTextField("33.0", 3);
        tfSalesTarget.addFocusListener(this);
        pnlSettings.add(tfSalesTarget);
        btnSetSalesTarget = new JButton("Set");
        btnSetSalesTarget.addActionListener(this);
        pnlSettings.add(btnSetSalesTarget);
        
        mainPane.setBounds(new Rectangle(MAX_WIDTH, MAX_HEIGHT));
        //mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
        mainPane.add(pnlGraph);
        mainPane.add(pnlSettings);
       
        Container con = this.getContentPane();
		con.add(mainPane);
        validate();
        
        addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent e) 
            {
                System.exit(0);
            }
        });
	}
	
	public void actionPerformed(ActionEvent arg0) 
	{
		Object source = arg0.getSource();

		if(source == btnSetSalesTarget)
		{
			try
			{
				double targetCheck = Double.parseDouble(tfSalesTarget.getText());
				
				if (targetCheck > 100)
					targetCheck = 100;
				else if (targetCheck < 0)
					targetCheck = 0;
				
				myRetailerAgent.setMarketShareExpected(targetCheck/100);
			}
			catch (Exception exc)
			{
				JOptionPane.showMessageDialog(this, "Cannot update sales target. Error:" + exc.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	@Override
	public void focusGained(FocusEvent arg0) 
	{
		JTextField source = (JTextField)arg0.getSource();
		if(source != null)
		{
			//source.setText("");
		}
	}
	
	@Override
	public void focusLost(FocusEvent arg0) 
	{
		// Nothing
	}
	
	public void UpdateFromRetailerAgent(int currentTickCount, float price, double powerNow, double powerSupplied, int sales, int requests) 
	{
		
		UpdateChart(currentTickCount, price, powerNow/powerSupplied, (float)sales/(float)requests);
	}
	
	/**
     * Display the chart in a swing window.
     *
     *
     * @param urlString
     *            the url string to display.
     * @throws IOException
     */
   /* private void displayUrlString(final String urlString, JLabel holder) throws IOException
    {
    	lblGraphImageBuff = new JLabel(new ImageIcon(ImageIO.read(new URL(urlString))));
    	lblGraphImageBuff.setVisible(holder.isVisible());
    	pnlGraph.removeAll();
    	holder = lblGraphImageBuff;
    	pnlGraph.add(holder,BorderLayout.EAST);
    	pnlGraph.validate();
        validate();
    }*/
    
    protected void InitChart()
    {
    	CurrentPriceDollars = new ArrayList<Double>(NUM_POINTS);
    	powerPercent = new ArrayList<Double>(NUM_POINTS);
    	salesPercent = new ArrayList<Double>(NUM_POINTS);
    	
    	double targetSpending = myRetailerAgent.getCurrentPrice();
    	
    	for (int i = 0; i < NUM_POINTS; i++) 
    	{
    		powerPercent.add(1.0);
    		salesPercent.add(0.0);
            CurrentPriceDollars.add(targetSpending);
        }
    }
    
    public static double[] toPrimitive(Double[] array) 
    {
    	if (array == null)
    		return null;
    	else if (array.length == 0)
    		return new double[0];
    	
    	final double[] result = new double[array.length];
    	
    	for (int i = 0; i < array.length; i++)
    		result[i] = array[i].doubleValue();
    	
    	return result;
    }
    
   
    protected void UpdateChart(int currentTickCount, double priceThisPeriod, double powerPercentThisPeriod, double salesPercentThisPeriod)
    {    	
    	CurrentPriceDollars.add(priceThisPeriod);
    	
    	if(CurrentPriceDollars.size() > NUM_POINTS)
    		CurrentPriceDollars.remove(0);
    	
    	Double[] temp = new Double[NUM_POINTS];
    	CurrentPriceDollars.toArray(temp);
    	
    	Line linePrice = Plots.newLine(DataUtil.scaleWithinRange(0.10, 0.26, toPrimitive(temp)), SKYBLUE, "Current Price");
    	linePrice.setLineStyle(LineStyle.newLineStyle(3, 1, 0));
    	linePrice.addShapeMarkers(Shape.DIAMOND, SKYBLUE, 12);
    	linePrice.addShapeMarkers(Shape.DIAMOND, Color.WHITE, 8);
        
        chartPrice = GCharts.newLineChart(linePrice);
        chartPrice.setSize(CHART_WIDTH, CHART_HEIGHT);
        
        chartPrice.setTitle("Retailer Pricing", WHITE, 14);
        chartPrice.setGrid(0.01, 0.01, 3, 2);

        AxisStyle axisStyle = AxisStyle.newAxisStyle(WHITE, 12, AxisTextAlignment.CENTER);
        
        AxisLabels xAxisExplainLabel = AxisLabelsFactory.newAxisLabels("Hours (24 hours windows)", 50.0);
        xAxisExplainLabel.setAxisStyle(AxisStyle.newAxisStyle(WHITE, 14, AxisTextAlignment.CENTER));
        AxisLabels xAxisNumericLabel = AxisLabelsFactory.newNumericRangeAxisLabels(0.0, TradingConst.HOURS_IN_DAY, 3);
        xAxisNumericLabel.setAxisStyle(axisStyle);
        
        AxisLabels yAxisExplainLabel = AxisLabelsFactory.newAxisLabels("$", 50.0);
        yAxisExplainLabel.setAxisStyle(axisStyle);
        AxisLabels yAxisNumericLabel = AxisLabelsFactory.newNumericRangeAxisLabels(0.10, 0.26, 0.02);
        yAxisNumericLabel.setAxisStyle(axisStyle);
        
        chartPrice.addXAxisLabels(xAxisExplainLabel);
        chartPrice.addXAxisLabels(xAxisNumericLabel);
        chartPrice.addYAxisLabels(yAxisExplainLabel);
        chartPrice.addYAxisLabels(yAxisNumericLabel);
        
        // Defining background and chart fills.
        chartPrice.setBackgroundFill(Fills.newSolidFill(Color.newColor("1F1D1D")));
        LinearGradientFill fill = Fills.newLinearGradientFill(0, Color.newColor("363433"), 100);
        fill.addColorAndOffset(Color.newColor("2E2B2A"), 0);
        chartPrice.setAreaFill(fill);
        String url = chartPrice.toURLString();
        JLabel holder = lblRetailerPriceImage;
        holder.setVisible(true);
        
        if(holder.isVisible())
        {
	        try 
	        {
	        	lblGraphImageBuffPrice = new JLabel(new ImageIcon(ImageIO.read(new URL(url))));
	        	lblGraphImageBuffPrice.setVisible(holder.isVisible());
	        	pnlGraph.removeAll();
	        	holder = lblGraphImageBuffPrice;
	        	pnlGraph.add(holder,BorderLayout.WEST);
			} 
	        catch (IOException e) 
			{
				e.printStackTrace();
			}
        }  
        
        updateSalesChart(powerPercentThisPeriod, salesPercentThisPeriod);
    }
    
    protected void updateSalesChart(double powerPercentThisPeriod, double salesPercentThisPeriod)
    {
    	
    	powerPercent.add(powerPercentThisPeriod);
    	
    	if(powerPercent.size() > NUM_POINTS)
    		powerPercent.remove(0);
    	
    	salesPercent.add(salesPercentThisPeriod);
    	
    	if(salesPercent.size() > NUM_POINTS)
    		salesPercent.remove(0);
    	
    	Line linePowerPercent = Plots.newLine(DataUtil.scaleWithinRange(0.0, 1.0, powerPercent), Color.newColor("CA3D05"), "Power Remaining");
        linePowerPercent.setLineStyle(LineStyle.newLineStyle(3, 1, 0));
        linePowerPercent.addShapeMarkers(Shape.DIAMOND, Color.newColor("CA3D05"), 12);
        linePowerPercent.addShapeMarkers(Shape.DIAMOND, Color.WHITE, 8);

        Line lineSalesPercent = Plots.newLine(DataUtil.scaleWithinRange(0.0, 1.0, salesPercent), LIMEGREEN, "Sales Percentage");
        lineSalesPercent.setLineStyle(LineStyle.newLineStyle(3, 1, 0));
        lineSalesPercent.addShapeMarkers(Shape.DIAMOND, LIMEGREEN, 12);
        lineSalesPercent.addShapeMarkers(Shape.DIAMOND, Color.WHITE, 8);
    	
    	chartSales = GCharts.newLineChart(linePowerPercent, lineSalesPercent);
        chartSales.setSize(CHART_WIDTH, CHART_HEIGHT);
        chartSales.setTitle("Retailer Sales Statistics", WHITE, 14);
        chartSales.setGrid(0.01, 0.01, 3, 2);
    	
        AxisStyle axisStyle = AxisStyle.newAxisStyle(WHITE, 12, AxisTextAlignment.CENTER);
        
        AxisLabels xAxisExplainLabel = AxisLabelsFactory.newAxisLabels("Hours (24 hours windows)", 50.0);
        xAxisExplainLabel.setAxisStyle(AxisStyle.newAxisStyle(WHITE, 14, AxisTextAlignment.CENTER));
        AxisLabels xAxisNumericLabel = AxisLabelsFactory.newNumericRangeAxisLabels(0.0, TradingConst.HOURS_IN_DAY, 3);
        xAxisNumericLabel.setAxisStyle(axisStyle);
        
        AxisLabels yAxisExplainLabel = AxisLabelsFactory.newAxisLabels("%", 50.0);
        yAxisExplainLabel.setAxisStyle(axisStyle);
        AxisLabels yAxisNumericLabel = AxisLabelsFactory.newNumericRangeAxisLabels(0, 100, 10);
        yAxisNumericLabel.setAxisStyle(axisStyle);
        
        // Adding axis info to chart.
        chartSales.addXAxisLabels(xAxisExplainLabel);
        chartSales.addXAxisLabels(xAxisNumericLabel);
        chartSales.addYAxisLabels(yAxisExplainLabel);
        chartSales.addYAxisLabels(yAxisNumericLabel);
        
     // Defining background and chart fills.
        chartSales.setBackgroundFill(Fills.newSolidFill(Color.newColor("1F1D1D")));
        LinearGradientFill fill = Fills.newLinearGradientFill(0, Color.newColor("363433"), 100);
        fill.addColorAndOffset(Color.newColor("2E2B2A"), 0);
        chartSales.setAreaFill(fill);
        
        String url = chartSales.toURLString();
        JLabel holder = lblRetailerSalesImage;
        
        if(holder.isVisible())
        {
	        try 
	        {
	        	lblGraphImageBuffSales = new JLabel(new ImageIcon(ImageIO.read(new URL(url))));
	        	lblGraphImageBuffSales.setVisible(holder.isVisible());
	        	holder = lblGraphImageBuffSales;
	        	pnlGraph.add(holder,BorderLayout.EAST);
	        	pnlGraph.validate();
	            validate();
			} 
	        catch (IOException e) 
			{
				e.printStackTrace();
			}
        }  
        
        
    }
}